package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import util.RunMode;
import controller.MoveController;
import controller.UndoController;
import entity.Board;
import entity.Word;

/**
 * This is the BoardApplication class.
 */
public class BoardApplication {
	public JFrame frame;
	public BoardCanvas canvas = null;

	public JPanel outboundPanel;
	public JPanel inboundPanel;

	public JComboBox outboundTypeCombo1;
	public JComboBox outboundTypeCombo2;
	public JComboBox outboundTypeCombo3;
	public JComboBox outboundTypeCombo4;
	public JComboBox outboundTypeCombo5;
	public JComboBox outboundWordCombo1;
	public JComboBox outboundWordCombo2;
	public JComboBox outboundWordCombo3;
	public JComboBox outboundWordCombo4;
	public JComboBox outboundWordCombo5;

	public JComboBox inboundTypeCombo1;
	public JComboBox inboundTypeCombo2;
	public JComboBox inboundTypeCombo3;
	public JComboBox inboundTypeCombo4;
	public JComboBox inboundTypeCombo5;
	public PlaceholderTextField inboundWordField1;
	public PlaceholderTextField inboundWordField2;
	public PlaceholderTextField inboundWordField3;
	public PlaceholderTextField inboundWordField4;
	public PlaceholderTextField inboundWordField5;

	public JButton outboundCleanButton;
	public JButton inboundCleanButton;
	public JButton swapSendButton;

	private JTable table;
	private BoardTableModel tableModel;
	private JPanel detailsPanel;
	private JPanel canvasPanel;

	private RunMode mode;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					BoardApplication window = new BoardApplication();
					window.frame.setVisible(true);
					window.frame.setTitle("CyberPoetry Slam - Team Pasiphae's Client");
					window.frame.setBounds(50, 50, window.canvas.getWidth() + window.detailsPanel.getWidth(), 820);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public BoardApplication() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		final Board board = new Board();

		frame = new JFrame();

		detailsPanel = new JPanel();
		frame.getContentPane().add(detailsPanel, BorderLayout.EAST);
		detailsPanel.setLayout(null);
		detailsPanel.setPreferredSize(new Dimension(540, 540));

		JPanel tablePanel = new JPanel();
		tablePanel.setBounds(6, 334, 532, 461);
		detailsPanel.add(tablePanel);
		tablePanel.setBorder(new TitledBorder(null, "Unprotected Words", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		tableModel = new BoardTableModel();
		tableModel.updateWords(board.getUnprotectedWords());
		table = new JTable(tableModel);
		table.getColumnModel().getColumn(0).setPreferredWidth(10);
		table.getColumnModel().getColumn(1).setPreferredWidth(300);
		tablePanel.setLayout(null);

		table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent event) {
				if(event.getValueIsAdjusting() && table.getSelectedRow() >= 0){
					Word selected = board.getUnprotectedWords().get((board.getUnprotectedWords().size() - 1) - table.getSelectedRow());
					board.bringToFront(selected);
					
					selected.blink = true;
					
					updateTable(board.getUnprotectedWords());
					canvas.repaint();
				}
			}
		});

		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setBounds(6, 16, 520, 439);
		tablePanel.add(scrollPane);

		JPanel panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "Swap Request", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		panel_1.setBounds(6, 6, 532, 327);
		detailsPanel.add(panel_1);
		panel_1.setLayout(null);

		outboundPanel = new JPanel();
		outboundPanel.setBounds(6, 19, 253, 277);
		panel_1.add(outboundPanel);
		outboundPanel.setBorder(new TitledBorder(null, "Outbound", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		outboundPanel.setLayout(null);

		JLabel outboundTypeLabel = new JLabel("Type");
		outboundTypeLabel.setBounds(17, 19, 61, 16);
		outboundPanel.add(outboundTypeLabel);

		JLabel outboundWordLabel = new JLabel("Word");
		outboundWordLabel.setBounds(138, 19, 61, 16);
		outboundPanel.add(outboundWordLabel);

		outboundTypeCombo1 = new JComboBox();
		outboundTypeCombo1.setModel(new DefaultComboBoxModel(new String[] {"Select", "* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		outboundTypeCombo1.setBounds(6, 47, 107, 27);
		outboundPanel.add(outboundTypeCombo1);

		outboundTypeCombo2 = new JComboBox();
		outboundTypeCombo2.setModel(new DefaultComboBoxModel(new String[] {"Select", "* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		outboundTypeCombo2.setBounds(6, 86, 107, 27);
		outboundPanel.add(outboundTypeCombo2);

		outboundTypeCombo3 = new JComboBox();
		outboundTypeCombo3.setModel(new DefaultComboBoxModel(new String[] {"Select", "* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		outboundTypeCombo3.setBounds(6, 125, 107, 27);
		outboundPanel.add(outboundTypeCombo3);

		outboundTypeCombo4 = new JComboBox();
		outboundTypeCombo4.setModel(new DefaultComboBoxModel(new String[] {"Select", "* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		outboundTypeCombo4.setBounds(6, 164, 107, 27);
		outboundPanel.add(outboundTypeCombo4);

		outboundTypeCombo5 = new JComboBox();
		outboundTypeCombo5.setModel(new DefaultComboBoxModel(new String[] {"Select", "* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		outboundTypeCombo5.setBounds(6, 203, 107, 27);
		outboundPanel.add(outboundTypeCombo5);

		JSeparator separator = new JSeparator();
		separator.setForeground(Color.LIGHT_GRAY);
		separator.setOrientation(SwingConstants.VERTICAL);
		separator.setBounds(114, 19, 12, 215);
		outboundPanel.add(separator);

		outboundWordCombo1 = new JComboBox();
		outboundWordCombo1.setEnabled(false);
		outboundWordCombo1.setBounds(125, 47, 122, 27);
		outboundPanel.add(outboundWordCombo1);

		outboundWordCombo2 = new JComboBox();
		outboundWordCombo2.setEnabled(false);
		outboundWordCombo2.setBounds(125, 86, 122, 27);
		outboundPanel.add(outboundWordCombo2);

		outboundWordCombo3 = new JComboBox();
		outboundWordCombo3.setEnabled(false);
		outboundWordCombo3.setBounds(125, 125, 122, 27);
		outboundPanel.add(outboundWordCombo3);

		outboundWordCombo4 = new JComboBox();
		outboundWordCombo4.setEnabled(false);
		outboundWordCombo4.setBounds(125, 164, 122, 27);
		outboundPanel.add(outboundWordCombo4);

		outboundWordCombo5 = new JComboBox();
		outboundWordCombo5.setEnabled(false);
		outboundWordCombo5.setBounds(125, 203, 122, 27);
		outboundPanel.add(outboundWordCombo5);

		outboundCleanButton = new JButton("Clean");
		outboundCleanButton.setBounds(6, 240, 241, 29);
		outboundPanel.add(outboundCleanButton);

		inboundPanel = new JPanel();
		inboundPanel.setBounds(271, 19, 253, 277);
		panel_1.add(inboundPanel);
		inboundPanel.setLayout(null);
		inboundPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Inbound", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));

		JLabel label = new JLabel("Type");
		label.setBounds(17, 19, 61, 16);
		inboundPanel.add(label);

		JLabel label_1 = new JLabel("Word");
		label_1.setBounds(138, 19, 61, 16);
		inboundPanel.add(label_1);

		inboundTypeCombo1 = new JComboBox();
		inboundTypeCombo1.setModel(new DefaultComboBoxModel(new String[] {"* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		inboundTypeCombo1.setBounds(6, 47, 107, 27);
		inboundPanel.add(inboundTypeCombo1);

		inboundTypeCombo2 = new JComboBox();
		inboundTypeCombo2.setModel(new DefaultComboBoxModel(new String[] {"* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		inboundTypeCombo2.setBounds(6, 86, 107, 27);
		inboundPanel.add(inboundTypeCombo2);

		inboundTypeCombo3 = new JComboBox();
		inboundTypeCombo3.setModel(new DefaultComboBoxModel(new String[] {"* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		inboundTypeCombo3.setBounds(6, 125, 107, 27);
		inboundPanel.add(inboundTypeCombo3);

		inboundTypeCombo4 = new JComboBox();
		inboundTypeCombo4.setModel(new DefaultComboBoxModel(new String[] {"* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		inboundTypeCombo4.setBounds(6, 164, 107, 27);
		inboundPanel.add(inboundTypeCombo4);

		inboundTypeCombo5 = new JComboBox();
		inboundTypeCombo5.setModel(new DefaultComboBoxModel(new String[] {"* (Any)", "Noun", "Pronoun", "Verb", "Adverb", "Adjective", "Preposition", "Article", "Number", "Suffix", "Determiner", "Conjunction"}));
		inboundTypeCombo5.setBounds(6, 203, 107, 27);
		inboundPanel.add(inboundTypeCombo5);

		JSeparator separator_1 = new JSeparator();
		separator_1.setOrientation(SwingConstants.VERTICAL);
		separator_1.setForeground(Color.LIGHT_GRAY);
		separator_1.setBounds(114, 19, 12, 215);
		inboundPanel.add(separator_1);

		inboundCleanButton = new JButton("Clean");
		inboundCleanButton.setBounds(6, 242, 241, 29);
		inboundPanel.add(inboundCleanButton);

		inboundWordField1 = new PlaceholderTextField();
		inboundWordField1.setPlaceholder("* (Any)");
		inboundWordField1.setBounds(125, 45, 122, 28);
		inboundPanel.add(inboundWordField1);
		inboundWordField1.setColumns(10);

		inboundWordField2 = new PlaceholderTextField();
		inboundWordField2.setPlaceholder("* (Any)");
		inboundWordField2.setColumns(10);
		inboundWordField2.setBounds(125, 84, 122, 28);
		inboundPanel.add(inboundWordField2);

		inboundWordField3 = new PlaceholderTextField();
		inboundWordField3.setPlaceholder("* (Any)");
		inboundWordField3.setColumns(10);
		inboundWordField3.setBounds(125, 123, 122, 28);
		inboundPanel.add(inboundWordField3);

		inboundWordField4 = new PlaceholderTextField();
		inboundWordField4.setPlaceholder("* (Any)");
		inboundWordField4.setColumns(10);
		inboundWordField4.setBounds(125, 162, 122, 28);
		inboundPanel.add(inboundWordField4);

		inboundWordField5 = new PlaceholderTextField();
		inboundWordField5.setPlaceholder("* (Any)");
		inboundWordField5.setColumns(10);
		inboundWordField5.setBounds(125, 201, 122, 28);
		inboundPanel.add(inboundWordField5);
		
		swapSendButton = new JButton("Send");
		swapSendButton.setBounds(6, 295, 518, 29);
		panel_1.add(swapSendButton);

		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		canvasPanel = new JPanel();
		frame.getContentPane().add(canvasPanel, BorderLayout.CENTER);
		canvasPanel.setLayout(null);
		canvas = new BoardCanvas(board);
		canvas.setLocation(0, 0);
		canvasPanel.add(canvas);
		canvas.setSize(800, 800);

		MoveController mc = new MoveController(this, board, RunMode.DEFAULT);
		final UndoController uc = new UndoController(this, board);

		canvas.addMouseMotionListener(mc);
		canvas.addMouseListener(mc);

		KeyEventPostProcessor kepp = new KeyEventPostProcessor() {
			public boolean postProcessKeyEvent(KeyEvent e) {
				if(e.getID() == 401){//Key PRESSED
					if(e.getKeyChar() == 'z' || e.getKeyChar() == '' || e.getKeyChar() == '?'){
						if(e.getModifiers() == 4 || e.getModifiers() == 2){
							uc.undo();
						}else if(e.getModifiers() == 3){
							uc.redo();
						}
					}
				}
				return false;
			}
		};

		KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
		kfm.addKeyEventPostProcessor(kepp);
	}

	/**
	 * Revert the order of the words in the ArrayList. 
	 * @param words
	 */
	public void updateTable(ArrayList<Word> words){
		ArrayList<Word> reverted = new ArrayList<Word>();

		for(Word w : words){
			reverted.add(0, w);
		}

		tableModel.updateWords(reverted);
	}

	/**
	 * Get the canvas of the board. 
	 * @return
	 */
	public BoardCanvas getCanvas() {
		return canvas;
	}

	/**
	 * Get the run mode. 
	 * @return
	 */
	public RunMode getRunMode() {
		return mode;
	}

	/**
	 * Set the run mode. 
	 */
	public void setRunMode(RunMode mode) {
		this.mode = mode;

	}
}
